/* * UFO Saved Game Editor * Copyright (C) 2010 Christopher Davoren * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package net.rubikscomplex.ufosge.gui; import java.awt.Toolkit; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.text.NumberFormat; import java.text.ParseException; import javax.swing.JTextField; import javax.swing.text.AbstractDocument; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.DocumentFilter; import javax.swing.text.DocumentFilter.FilterBypass; import javax.swing.text.NumberFormatter; import net.rubikscomplex.ufosge.util.Util; /** * * @author Chris Davoren */ public class NumericFormattedTextField extends JTextField implements FocusListener { protected long minValue; protected long maxValue; protected NumberFormatter formatter; long value = 0; public NumericFormattedTextField(long minValue, long maxValue, NumberFormat format) { super(); this.minValue = minValue; this.maxValue = maxValue; value = 0; NumberFormat numFormat = format; if (format == null) { numFormat = NumberFormat.getInstance(); numFormat.setMaximumFractionDigits(0); numFormat.setParseIntegerOnly(true); } this.formatter = new NumberFormatter(numFormat); ((AbstractDocument)getDocument()).setDocumentFilter(new NumericFormattedDocumentFilter(minValue, maxValue, this)); addFocusListener(this); try { this.setText(formatter.valueToString(value)); } catch (ParseException e) { this.setText("0"); } this.setToolTipText("Value must be between " + minValue + " and " + maxValue); } public NumberFormatter getFormatter() { return formatter; } public void focusGained(FocusEvent e) { // System.out.println("Focus gained! Value = " + value + " | Focus = " + this.hasFocus()); setText(Long.toString(value)); } public void focusLost(FocusEvent e) { // System.out.println("Focus lost!" + this.hasFocus()); try { value = Long.parseLong(getText()); setText(formatter.valueToString(value)); } catch (NumberFormatException fe) { value = 0; } catch (ParseException pe) { setText(Long.toString(value)); } } public long getValue() { return value; } public void setValue(long value) { // System.out.println("Value: " + value); this.value = value; if (!hasFocus()) { try { String str = formatter.valueToString(value); // System.out.println("[NumericFormattedTextField] str = " + str); setText(str); } catch (ParseException e) { setText("0"); } } else { setText(Long.toString(value)); } } class NumericFormattedDocumentFilter extends DocumentFilter { long minValue; long maxValue; NumericFormattedTextField field; public NumericFormattedDocumentFilter(long minValue, long maxValue, NumericFormattedTextField field) { this.minValue = minValue; this.maxValue = maxValue; this.field = field; } @Override public void insertString(FilterBypass fb, int offs, String str, AttributeSet a) throws BadLocationException { // System.out.println("[NumericFormattedDocumentFilter] insert()"); try { Long.parseLong(str); } catch (NumberFormatException e) { Toolkit.getDefaultToolkit().beep(); Util.displayTooltip(field); return; } String docText = fb.getDocument().getText(0, fb.getDocument().getLength()); String preText = docText.substring(0, offs); String postText = docText.substring(offs); String finalText = preText + str + postText; long numericValue; if (!field.hasFocus()) { try { numericValue = ((Number)field.getFormatter().stringToValue(field.getText())).longValue(); } catch (ParseException e) { Toolkit.getDefaultToolkit().beep(); Util.displayTooltip(field); return; } } numericValue = Long.parseLong(finalText); if (numericValue >= minValue && numericValue <= maxValue) { value = numericValue; fb.insertString(offs, str, a); } else { Util.displayTooltip(field); Toolkit.getDefaultToolkit().beep(); } } @Override public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a) throws BadLocationException { // System.out.println("[NumericFormattedDocumentFilter] replace()"); String docText = fb.getDocument().getText(0, fb.getDocument().getLength()); String preStr = docText.substring(0, offs); String postStr = docText.substring(offs + length); String newStr = preStr + str + postStr; if (newStr.length() == 0) { super.replace(fb, 0, docText.length(), "0" , a); return; } // System.out.println (" : newStr = " + newStr); long numericValue; if (!field.hasFocus()) { try { // System.out.println (" : hasFocus"); numericValue = ((Number)field.getFormatter().stringToValue(newStr)).longValue(); fb.replace(offs, length, str, a); return; } catch (ParseException e) { // System.out.println(e); Toolkit.getDefaultToolkit().beep(); Util.displayTooltip(field); return; } } try { // System.out.println(" : No focus."); numericValue = Long.parseLong(newStr); if (numericValue >= minValue && numericValue <= maxValue) { value = numericValue; fb.replace(offs, length, str, a); } else { // System.out.println("Number out of bounds."); Toolkit.getDefaultToolkit().beep(); Util.displayTooltip(field); } } catch (NumberFormatException e) { // System.out.println(e); Toolkit.getDefaultToolkit().beep(); Util.displayTooltip(field); } } public void remove(DocumentFilter.FilterBypass fb, int offs, int length) throws BadLocationException { // System.out.println("[NumericFormattedDocumentFilter] remove()"); String docText = fb.getDocument().getText(0, fb.getDocument().getLength()); String newStr = docText.substring(0, offs) + docText.substring(offs + length); if (newStr.length() == 0) { // System.out.println(" : calling replace() instead."); fb.replace(0, docText.length(), "0", null); if (docText.length() == 0) { Toolkit.getDefaultToolkit().beep(); Util.displayTooltip(field); } return; } long numericValue; if (!field.hasFocus()) { try { numericValue = ((Number)field.getFormatter().stringToValue(field.getText())).longValue(); fb.remove(offs, length); return; } catch (ParseException e) { Toolkit.getDefaultToolkit().beep(); Util.displayTooltip(field); return; } } try { numericValue = Long.parseLong(newStr); if (numericValue >= minValue && numericValue <= maxValue) { value = numericValue; fb.remove(offs, length); } else { Toolkit.getDefaultToolkit().beep(); Util.displayTooltip(field); } } catch (NumberFormatException e) { Toolkit.getDefaultToolkit().beep(); Util.displayTooltip(field); } } } }